
package com.hlkj.pay.app.merchant.ext.impl.yftpay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.yftpay.YftScenePayOrderExtPt;
import com.hlkj.pay.app.merchant.ext.impl.yftpay.constant.YftPayConstant;
import com.hlkj.pay.app.merchant.ext.impl.yftpay.constant.YftPayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.yftpay.dto.YftPayConfig;
import com.hlkj.pay.app.merchant.ext.impl.yftpay.utils.HttpUtils;
import com.hlkj.pay.app.merchant.ext.impl.yftpay.utils.PayDigestUtilOK;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.common.ICommonAppConfigService;
import com.hlkj.pay.util.MerchantUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * 主扫统一下单 用户扫支付码
 *
 * @author HlpayTeam
 * @date 2024/11/18 13:07
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = YftPayExtConstant.PAY)
public class YftPayScanPayOrderExtPt extends YftPaySceneCommonPayOrder implements YftScenePayOrderExtPt {

    private final ICommonAppConfigService commonAppConfigService;

    @Override
    public void submitChannelPayOrder(ChannelPayOrderContext channelPayOrderContext) {
        // 配置转换
        ProviderChannelConfigDO providerChannelConfigDO = channelPayOrderContext.getProviderChannelConfigDO();
        String channelConfig = providerChannelConfigDO.getParamsConfig();
        YftPayConfig yftPayConfig = getPayConfig(channelConfig, channelPayOrderContext.getMerchantAppChannelDO());
        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        try {
            PayWayDO payWayDO = channelPayOrderContext.getPayWayDO();
            JSONObject paramMap = new JSONObject();
            paramMap.set("mchId", yftPayConfig.getMchId());                               // 商户ID
            paramMap.set("mchOrderNo", payOrderDO.getPayOrderNo());     // 商户订单号
            paramMap.set("productId", getDataType(payWayDO));                       // 支付产品
            paramMap.set("amount", MerchantUtils.YuanToFen(payOrderDO.getAmount()));                                // 支付金额,单位分
            paramMap.set("currency", "cny");                            // 币种, cny-人民币
            paramMap.set("clientIp", payOrderDO.getClientIp());                 // 用户地址,微信H5支付时要真实的
            paramMap.set("subject", payOrderDO.getSubject());
            if (!StringUtils.hasText(payOrderDO.getDescription())) {
                paramMap.set("body", payOrderDO.getSubject());
            } else
                paramMap.set("body", payOrderDO.getDescription());
            // 回调URL
            paramMap.set("notifyUrl", channelPayOrderContext.getNotifyUrl());
            paramMap.set("returnUrl", channelPayOrderContext.getRedirectUrl());

            String reqSign = PayDigestUtilOK.getSign(paramMap, yftPayConfig.getMd5Key());
            paramMap.set("sign", reqSign);                              // 签名
            String reqData = "params=" + paramMap.toString();
            String url = domain(channelPayOrderContext.isTest()) + YftPayConstant.TRADE_CREATE + "?" + reqData;
            log.info("银付通下单req参数:{}", reqData);
            String response = HttpUtils.get(url);
            log.info("银付通下单返回参数:{}", response);

            JSONObject ordeRsp = JSONUtil.parseObj(response);
            if ("SUCCESS".equals(ordeRsp.getStr("retCode"))) {
                JSONObject payParams = ordeRsp.getJSONObject("payParams");
                channelPayOrderContext.setPayInfo(payParams.getStr("codeUrl"));
                channelPayOrderContext.setPayDataType("pay_url");
                channelPayOrderContext.setInsOrderNo(ordeRsp.getStr("payOrderId"));
            } else {
                String respDesc = ordeRsp.getStr("retMsg");
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(respDesc)) {
                    channelPayOrderContext.setRemark(respDesc);
                } else {
                    channelPayOrderContext.setRemark("银付通下单查询返回错误信息为空,错误码为:" + ordeRsp.getStr("retCode"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("银付通下单请求失败 message:{}", e.getMessage(), e);
            channelPayOrderContext.setRemark("银付通下单请求失败,失败信息" + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    private String getDataType(PayWayDO payWayDO) {
        PayEnums.SCENE_PAY_TYPE scenePayType = PayEnums.SCENE_PAY_TYPE.from(payWayDO.getSubType());
        PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
        if (Objects.isNull(scenePayType) || Objects.isNull(payType)) return "";
        switch (payType) {
            case ALIPAY:
                switch (scenePayType) {
                    case H5:
                    case PC:
                    case QR:
                    case JSAPI:
                    case APP:
                        return "8006";
                }
            case WECHAT:
                switch (scenePayType) {
                    case JSAPI:
                        return "8005";
                    case QR:
                        return "8002";
                    case H5:
                    case PC:
                        return "8006";
                }
        }
        return "";
    }

    @Override
    public void queryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void closeChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonCloseChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void queryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelClosePayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void refundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public void queryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonQueryRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public boolean refundApply(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        return true;
    }

    @Override
    public CommonResult<String> channelOrderCode(ChannelPayOrderContext channelPayOrderContext) {
        return CommonResult.success();
    }

}
